/*
============================================================================
 Name        : $(Basename)Server.cpp
 Author      : $(Author)
 Version     :
 Copyright   : $(Copyright)
 Description : $(Basename)Server.
============================================================================
*/

#include <e32math.h>
#include "$(Basename)Session.h"
#include "$(Basename)Server.h"

#ifdef __WINS__
EXPORT_C TInt WinsMain()
	{
	return reinterpret_cast<TInt>(&C$(Basename)Server::EntryPoint);
	}

GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
	{
	return KErrNone;
	}
#else
TInt E32Main()
	{
	return C$(Basename)Server::EntryPoint(NULL);
	}
#endif

TInt C$(Basename)Server::EntryPoint(TAny* /*aNone*/)
	{
	CTrapCleanup* cleanupStack = CTrapCleanup::New();
	if(!cleanupStack)
		{
		PanicServer(ECreateTrapCleanup);
		}

	TRAPD(leave, ThreadMainL());
	if(leave)
		{
		PanicServer(ESrvCreateServer);
		}

	delete cleanupStack;
	cleanupStack = NULL;

	return KErrNone;
	}

void C$(Basename)Server::ThreadMainL()
	{
	CActiveScheduler* activeScheduler = new(ELeave) CActiveScheduler();
	CleanupStack::PushL(activeScheduler);

	CActiveScheduler::Install(activeScheduler);

	C$(Basename)Server::NewLC();

	RSemaphore semaphore;
	User::LeaveIfError(semaphore.OpenGlobal(K$(Basename)ServerSemaphoreName));
	semaphore.Signal();
	semaphore.Close();

	CActiveScheduler::Start();

	CleanupStack::PopAndDestroy(2);
	}

C$(Basename)Server* C$(Basename)Server::NewL()
	{
	C$(Basename)Server* server = C$(Basename)Server::NewLC();
	CleanupStack::Pop(server);
	return server;
	}

C$(Basename)Server* C$(Basename)Server::NewLC()
	{
	C$(Basename)Server* server = new(ELeave) C$(Basename)Server(EPriorityNormal);
	CleanupStack::PushL(server);
	server->ConstructL();
	return server;
	}

C$(Basename)Server::C$(Basename)Server(TInt aPriority) : CServer(aPriority)
	{
	}

void C$(Basename)Server::ConstructL()
	{
	StartL(K$(Basename)ServerName);
	}

C$(Basename)Server::~C$(Basename)Server()
	{
	delete iExampleHeartbeat;
	iExampleHeartbeat = NULL;
	}

CSharableSession* C$(Basename)Server::NewSessionL(const TVersion& aVersion) const
	{
	if(!User::QueryVersionSupported(TVersion(K$(Basename)ServMajorVersionNumber,
			K$(Basename)ServMinorVersionNumber,
			K$(Basename)ServBuildVersionNumber),
			aVersion))
		{
		User::Leave(KErrNotSupported);
		}

	RThread client = Message().Client();
	return C$(Basename)ServerSession::NewL(client, *const_cast<C$(Basename)Server*>(this));
	}

void C$(Basename)Server::IncrementSessions()
	{
	iSessionCount++;
	}

void C$(Basename)Server::DecrementSessions()
	{
	iSessionCount--;
	if(iSessionCount <= 0)
		{
		CActiveScheduler::Stop();
		}
	}

TInt C$(Basename)Server::RunError(TInt aError)
	{
	if(aError == KErrBadDescriptor)
		{
		PanicClient(Message(), EBadDescriptor);
		}
	else
		{
		Message().Complete(aError);
		}

	// The leave will result in an early return from CServer::RunL(), skipping
	// the call to request another message. So do that now in order to keep the
	// server running.
	ReStart();

	return KErrNone;
	}

void C$(Basename)Server::PanicClient(const RMessage& aMessage, T$(Basename)ServPanic aPanic)
	{
	aMessage.Panic(K$(Basename)Server, aPanic);
	}

void C$(Basename)Server::PanicServer(T$(Basename)ServPanic aPanic)
	{
	User::Panic(K$(Basename)Server, aPanic);
	}

void C$(Basename)Server::WaitForTickL()
	{
	if(!iExampleHeartbeat)
		{
		iExampleHeartbeat = CHeartbeat::NewL(EPriorityHigh);
		iExampleHeartbeat->Start(ETwelveOClock, this);
		}
	}

void C$(Basename)Server::Beat()
	{
	SendTimeToSessions();
	}

void C$(Basename)Server::Synchronize()
	{
	SendTimeToSessions();
	}

void C$(Basename)Server::SendTimeToSessions()
	{
	iSessionIter.SetToFirst();
	C$(Basename)ServerSession* session = reinterpret_cast<C$(Basename)ServerSession*>(iSessionIter++);
	while(session)
		{
		session->SendTimeToClient();
		session = reinterpret_cast<C$(Basename)ServerSession*>(iSessionIter++);
		}
	}
